home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / ucrasm27.zip / SOURCE.ZIP / APNDCURM.ASM < prev    next >
Assembly Source File  |  1992-06-12  |  6KB  |  279 lines

  1.  
  2. ; Need to include "lists.a" in order to get list structure definition.
  3.  
  4.         include    lists.a
  5.         extrn    sl_malloc:far
  6.  
  7.  
  8. wp        equ    <word ptr>        ;I'm a lazy typist
  9.  
  10.  
  11. ; Special case to handle MASM 6.0 vs. all other assemblers:
  12. ; If not MASM 5.1 or MASM 6.0, set the version to 5.00:
  13.  
  14.         ifndef    @version
  15. @version    equ    500
  16.         endif
  17.  
  18.  
  19.  
  20. StdGrp        group    stdlib,stddata
  21. stddata        segment    para public 'sldata'
  22. stddata        ends
  23.  
  24. stdlib        segment    para public 'slcode'
  25.         assume    cs:stdgrp
  26.  
  27.  
  28. ; sl_AppendCurm-    DX:SI points at a block of data bytes.
  29. ;            ES:DI points at a list.
  30. ;            This routine allocates storage for a new node on the
  31. ;            heap, copies the data from DX:SI to the new node,
  32. ;            and then links in the new node to the list after
  33. ;            the current node.
  34. ;
  35. ;            Returns the carry set if memory allocation error
  36. ;            occurs.
  37. ;
  38. ; Randall Hyde  3/13/92
  39. ;
  40.  
  41.         public    sl_AppendCurm
  42. sl_AppendCurm    proc    far
  43.         pushf
  44.         push    ds
  45.         push    ax
  46.         push    bx
  47.         push    cx
  48.         push    es
  49.         push    di
  50.         cld
  51.  
  52.  
  53.  
  54.         if    @version ge 600
  55.  
  56. ; MASM 6.0 version goes here
  57.  
  58. ; First, allocate storage for the new node:
  59.  
  60.         mov    cx, es:[di].List.ListSize
  61.         push    cx            ;Save for later
  62.         add    cx, size NODE        ;Add in overhead
  63.         call    sl_malloc        ;Go get the memory
  64.         pop    cx            ;Get real length back.
  65.         jc    BadAppend        ;If malloc error
  66.         push    di            ;Save ptr to new NODE.
  67.  
  68. ; Compute offset to actual data area (skipping over list pointers, etc.)
  69.  
  70.         add    di, size Node
  71.  
  72.  
  73.         mov    ds, dx
  74.     rep    movsb                ;Copy the node's data.
  75.         pop    si            ;Get ptr to original node
  76.         mov    cx, es            ;Make ds:si point at node.
  77.         mov    ds, cx
  78.         pop    di            ;Get ptr to list var
  79.         pop    es
  80.         push    es
  81.         push    di
  82.  
  83. ; At this point, DS:SI points at the new node on the heap and ES:DI points
  84. ; at the list variable.
  85.  
  86. ; See if the the list is empty:
  87.  
  88.         cmp    wp es:[di].List.Head+2, 0
  89.         jne    ListHasNodes
  90.  
  91. ; If this is an empty list (list is empty if HEAD is NIL), then build the
  92. ; list from this single node.
  93.  
  94.         mov    wp es:[di].List.Tail, si
  95.         mov     wp es:[di].List.Head, si
  96.         mov    wp es:[di].List.CurrentNode, si
  97.         mov    wp es:[di].List.Tail+2, ds
  98.         mov    wp es:[di].List.Head+2, ds
  99.         mov    wp es:[di].List.CurrentNode+2, ds
  100.  
  101. ; Set the link fields of this new node to NIL.
  102.  
  103.         mov    wp [si].Node.Next, 0
  104.         mov    wp [si].Node.Prev, 0
  105.         mov    wp [si].Node.Next+2, 0
  106.         mov    wp [si].Node.Prev+2, 0
  107.  
  108.         pop    di
  109.         pop    es
  110.         jmp    GoodAppend
  111.  
  112.  
  113. ;If there were items in the list, perform the insert down here.
  114.  
  115. ListHasNodes:    les    di, es:[di].List.CurrentNode    ;Get ptr to item
  116.         mov    ax, wp es:[di].Node.Next    ;Get ptr to next
  117.         mov    bx, wp es:[di].Node.Next+2    ; node and save.
  118.  
  119. ; Use the address of CurrentNode as the previous ptr for the new node.
  120.  
  121.         mov    wp ds:[si].Node.Prev, di     ;Patch in link
  122.         mov    wp ds:[si].Node.Prev+2, es
  123.  
  124. ; Okay, store the new node's address into the NEXT field of the current node
  125.  
  126.         mov    wp es:[di].Node.Next, si    ;Patch in fwd ptr
  127.         mov    wp es:[di].Node.Next+2, ds
  128.  
  129. ; Set the NEXT field of the new node to the original previous node.
  130.  
  131.         mov    wp ds:[si].Node.Next, ax
  132.         mov    wp ds:[si].Node.Next+2, bx
  133.  
  134. ; Patch in the Prev field of the original NEXT node:
  135.  
  136.         mov    es, bx
  137.         mov    di, ax
  138.         mov    wp es:[di].Node.Prev, si
  139.         mov    wp es:[di].Node.Prev+2, ds
  140.  
  141. ; Set the CurrentNode ptr to the new node
  142.  
  143.         pop    di            ;Retrive ptr to list var.
  144.         pop    es
  145.         mov    wp es:[di].List.CurrentNode, si
  146.         mov    wp es:[di].List.CurrentNode+2, ds
  147.  
  148.  
  149.  
  150.  
  151.  
  152.         else
  153.  
  154. ; All other assemblers come down here:
  155.  
  156.  
  157. ; First, allocate storage for the new node:
  158.  
  159.         mov    cx, es:[di].ListSize
  160.         push    cx            ;Save for later
  161.         add    cx, size NODE        ;Add in overhead
  162.         call    sl_malloc        ;Go get the memory
  163.         pop    cx            ;Get real length back.
  164.         jnc    GoodApnd
  165.         jmp    BadAppend        ;If malloc error
  166.  
  167. GoodApnd:    push    di            ;Save ptr to new NODE.
  168.  
  169. ; Compute offset to actual data area (skipping over list pointers, etc.)
  170.  
  171.         add    di, size Node
  172.  
  173.  
  174.         mov    ds, dx
  175.     rep    movsb                ;Copy the node's data.
  176.         pop    si            ;Get ptr to original node
  177.         mov    cx, es            ;Make ds:si point at node.
  178.         mov    ds, cx
  179.         pop    di            ;Get ptr to list var
  180.         pop    es
  181.         push    es
  182.         push    di
  183.  
  184. ; At this point, DS:SI points at the new node on the heap and ES:DI points
  185. ; at the list variable.
  186.  
  187. ; See if the the list is empty:
  188.  
  189.         cmp    wp es:[di].Head+2, 0
  190.         jne    ListHasNodes
  191.  
  192. ; If this is an empty list (list is empty if HEAD is NIL), then build the
  193. ; list from this single node.
  194.  
  195.         mov    wp es:[di].Tail, si
  196.         mov     wp es:[di].Head, si
  197.         mov    wp es:[di].CurrentNode, si
  198.         mov    wp es:[di].Tail+2, ds
  199.         mov    wp es:[di].Head+2, ds
  200.         mov    wp es:[di].CurrentNode+2, ds
  201.  
  202. ; Set the link fields of this new node to NIL.
  203.  
  204.         mov    wp [si].Next, 0
  205.         mov    wp [si].Prev, 0
  206.         mov    wp [si].Next+2, 0
  207.         mov    wp [si].Prev+2, 0
  208.  
  209.         pop    di
  210.         pop    es
  211.         jmp    GoodAppend
  212.  
  213.  
  214. ;If there were items in the list, perform the insert down here.
  215.  
  216. ListHasNodes:    les    di, es:[di].CurrentNode    ;Get ptr to item
  217.         mov    ax, wp es:[di].Next    ;Get ptr to next
  218.         mov    bx, wp es:[di].Next+2    ; node and save.
  219.  
  220. ; Use the address of CurrentNode as the previous ptr for the new node.
  221.  
  222.         mov    wp ds:[si].Prev, di     ;Patch in link
  223.         mov    wp ds:[si].Prev+2, es
  224.  
  225. ; Okay, store the new node's address into the NEXT field of the current node
  226.  
  227.         mov    wp es:[di].Next, si    ;Patch in fwd ptr
  228.         mov    wp es:[di].Next+2, ds
  229.  
  230. ; Set the NEXT field of the new node to the original previous node.
  231.  
  232.         mov    wp ds:[si].Next, ax
  233.         mov    wp ds:[si].Next+2, bx
  234.  
  235. ; Patch in the Prev field of the original NEXT node:
  236.  
  237.         mov    es, bx
  238.         mov    di, ax
  239.         mov    wp es:[di].Prev, si
  240.         mov    wp es:[di].Prev+2, ds
  241.  
  242. ; Set the CurrentNode ptr to the new node
  243.  
  244.         pop    di            ;Retrive ptr to list var.
  245.         pop    es
  246.         mov    wp es:[di].CurrentNode, si
  247.         mov    wp es:[di].CurrentNode+2, ds
  248.  
  249.  
  250.  
  251.  
  252.  
  253.         endif
  254.  
  255. ; DANGER WILL ROBINSON! Multiple exit points.  Be wary of these if you
  256. ; change the way things are pushed on the stack.
  257.  
  258. GoodAppend:    pop    cx
  259.         pop    bx
  260.         pop    ax
  261.         pop    ds
  262.         popf
  263.         clc
  264.         ret
  265.  
  266. BadAppend:    pop    di
  267.         pop    es
  268.         pop    cx
  269.         pop    bx
  270.         pop    ax
  271.         pop    ds
  272.         popf
  273.         stc
  274.         ret
  275. sl_AppendCurm    endp
  276.  
  277. stdlib        ends
  278.         end
  279.